package so.sao.code.service.service.impl;

import static so.sao.code.service.infrastructure.EventsPublisher.publish;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

import javax.transaction.Transactional;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;

import so.sao.code.dto.request.TagBatchFormat;
import so.sao.code.service.domain.entity.EnterpriseCustomField;
import so.sao.code.service.domain.entity.TagBatch;
import so.sao.code.service.domain.entity.TagBatchConfig;
import so.sao.code.service.domain.event.TagBatchConfigCreateEvent;
import so.sao.code.service.domain.service.TagBatchConfigDomainService;
import so.sao.code.service.infrastructure.SessionContext;
import so.sao.code.service.infrastructure.dozer.Mapper;
import so.sao.code.service.infrastructure.enums.CodeMessage;
import so.sao.code.service.infrastructure.enums.OPERATION;
import so.sao.code.service.infrastructure.enums.PrintFileDownloadMethod;
import so.sao.code.service.infrastructure.enums.PrintFileFieldConfig;
import so.sao.code.service.infrastructure.model.vo.EnterpriseCustomFieldVO;
import so.sao.code.service.infrastructure.model.vo.TagBatchConfigVO;
import so.sao.code.service.infrastructure.utils.BeanUtils;
import so.sao.code.service.repository.EnterpriseCustomFieldDao;
import so.sao.code.service.repository.TagBatchConfigDao;
import so.sao.code.service.repository.TagBatchDao;
import so.sao.code.service.service.TagBatchConfigService;
import so.sao.data.dto.response.FactoryDTO;
import so.sao.data.dto.response.IndustrialComputerDTO;
import so.sao.data.feign.client.FactoryClient;
import so.sao.data.feign.client.IndustrialComputerClient;
import so.sao.top.core.util.RandomUtil;
import so.sao.top.core.util.mapper.JsonMapper;
import so.sao.top.core.util.rest.RestException;

@Service
public class TagBatchConfigServiceImpl implements TagBatchConfigService {

	@Autowired
	TagBatchConfigDao tagBatchConfigDao;

	@Autowired
	TagBatchDao tagBatchDao;

	@Autowired
	JsonMapper jsonMapper;
	@Autowired
	TagBatchConfigDomainService tagBatchConfigDomainService;
	@Autowired
	EnterpriseCustomFieldDao enterpriseCustomFieldDao;
	@Autowired
	IndustrialComputerClient industrialComputerClient;
	@Autowired
	FactoryClient factoryClient;

	@Autowired
	ApplicationEventPublisher publisher;
	@Autowired
	SessionContext context;

	@Override
	public TagBatchConfigVO findConfigByFormatId(Long formatId) {
		TagBatchConfig tagBatchConfig = tagBatchConfigDao.findOne(formatId);
		TagBatch tagBatch = tagBatchDao.findOne(tagBatchConfig.getTagBatchId());

		List<String> list = jsonMapper.fromCollectionJson(tagBatchConfig.getFieldsConfig(), String.class);
		List<List<EnterpriseCustomFieldVO>> fieldsConfigs = new ArrayList<>();
		switch (tagBatch.getType()) {
		case NORMAL:
		case ROLL:
			if (list.size() != 0) {
				List<EnterpriseCustomFieldVO> FieldsConfigsNameList = new ArrayList<>();
				String[] result = list.stream().findFirst().get().split("\\|");
				for (String fieldsConfigId : result) {
					FieldsConfigsNameList.add(getFieldsConfig(fieldsConfigId));
				}
				fieldsConfigs.add(FieldsConfigsNameList);
			}
			break;
		case PACKAGE:
		case DUPLICATE:
			if (list.size() != 0) {
				List<EnterpriseCustomFieldVO> FieldsConfigsNameList = new ArrayList<>();
				String[] result = list.stream().findFirst().get().split("\\|");
				for (String fieldsConfigId : result) {
					FieldsConfigsNameList.add(getFieldsConfig(fieldsConfigId));
				}
				fieldsConfigs.add(FieldsConfigsNameList);
				FieldsConfigsNameList = new ArrayList<>();
				String[] resultCode = list.get(1).split("\\|");
				for (String fieldsConfigId : resultCode) {
					FieldsConfigsNameList.add(getFieldsConfig(fieldsConfigId));
				}
				fieldsConfigs.add(FieldsConfigsNameList);
			}
			break;
		case WRAP:
			if (list.size() != 0) {
				List<EnterpriseCustomFieldVO> FieldsConfigsNameList = new ArrayList<>();
				String[] result = list.stream().findFirst().get().split("\\|");
				for (String fieldsConfigId : result) {
					FieldsConfigsNameList.add(getFieldsConfig(fieldsConfigId));
				}
				fieldsConfigs.add(FieldsConfigsNameList);
			}
			break;
		default:
			break;
		}
		TagBatchConfigVO vo = new TagBatchConfigVO();
		BeanUtils.copyProperties(vo, tagBatchConfig);
		if (tagBatchConfig.getTerminalId() != null && !tagBatchConfig.getTerminalId().equals(0L)) {
			Optional<IndustrialComputerDTO> result = Optional
					.ofNullable(industrialComputerClient.findById(tagBatchConfig.getTerminalId()));
			if(result.isPresent()){
				vo.setTerminalName(result.get().getName());
			}
		}
		if (tagBatchConfig.getPrintFactoryId() != null && !tagBatchConfig.getPrintFactoryId().equals(0L)) {
			Optional<FactoryDTO> factoryDTO = Optional
					.ofNullable(factoryClient.findById(tagBatchConfig.getPrintFactoryId()));
			if(factoryDTO.isPresent()){
				vo.setPrintFactoryName(factoryDTO.get().getName());
			}
		}
		vo.setFieldsConfigs(list);
		vo.setFieldsConfigsName(fieldsConfigs);
		return vo;
	}

	private EnterpriseCustomFieldVO getFieldsConfig(String fieldsConfigId) {
		EnterpriseCustomFieldVO enterpriseCustomField = new EnterpriseCustomFieldVO();
		if (fieldsConfigId != null) {
			enterpriseCustomField.setFieldKey(fieldsConfigId);
			if (!fieldsConfigId.startsWith("Classic_") && !fieldsConfigId.startsWith("Common_")) {
				enterpriseCustomField.setFieldName(PrintFileFieldConfig.fromValue(fieldsConfigId).getName());
			} else {
				List<EnterpriseCustomField> res = enterpriseCustomFieldDao.findByfieldKey(fieldsConfigId);
				enterpriseCustomField.setFieldName(res.stream().findFirst().get().getFieldName());
			}
		}
		return enterpriseCustomField;
	}

	@Transactional
	@Override
	public TagBatchConfig saveConfig(TagBatchFormat tagBatchFormat) {
		TagBatchConfig tagBatchConfig = Mapper.map(tagBatchFormat, TagBatchConfig.class);
		if (tagBatchConfig.getDownloadMethod() == PrintFileDownloadMethod.OnLine.getValue()
				&& tagBatchConfig.getTagCountPerLine() != 1) {
			tagBatchConfig.setTagCountPerLine(1);
		}
		TagBatch tagBatch = Optional.ofNullable(tagBatchDao.findOne(tagBatchConfig.getTagBatchId()))
				.orElseThrow(() -> new RestException(HttpStatus.NOT_FOUND, CodeMessage.CanNotFindTagBatch,
						tagBatchFormat.getTagBatchId()));
		if (!context.CURRECT_USER.getEseId().equals(1L)
				&& !tagBatch.getEseId().equals(context.CURRECT_USER.getEseId())) {
			throw new RestException(HttpStatus.BAD_REQUEST, CodeMessage.InvalidRequest);
		}
		// checkDomainLength(tagBatch.getCodeLength(), tagBatch.getSeqnumStart()
		// + tagBatch.getTagCount() - 1, tagBatchConfig.getUrlDomain(),
		// tagBatch.getSubDomain());
		List<String> fulfillFieldsConfig = fulfillFieldsConfig(tagBatch, tagBatchConfig.getTagCountPerLine(),
				tagBatchFormat.getFieldsConfigs());
		tagBatchConfig.setFieldsConfig(jsonMapper.toJson(fulfillFieldsConfig));
		tagBatchConfig.setTagCountPerLine(
				tagBatchConfigDomainService.computeCountPerLine(tagBatch, tagBatchFormat.getTagCountPerLine()));
		tagBatchConfig.setUrlDomain(tagBatch.getDomain());
		tagBatchConfig = tagBatchConfigDao.save(tagBatchConfig);
		if (!tagBatchConfig.isPlatformEncryption()) {
			tagBatch.setZipPassword(RandomUtil.getRandomUUID());
		}
		publish(new TagBatchConfigCreateEvent(tagBatch, tagBatchConfig, OPERATION.CONFIG));
		return tagBatchConfig;
	}

	// 补充未设置格式的字段，按照现有字段格式进行复制
	private List<String> fulfillFieldsConfig(TagBatch tagBatch, Integer preTagCountPerLine, List<String> fieldsConfig) {
		int fieldsConfigCount = fieldsConfig.size();
		int tagCountPerLine = tagBatchConfigDomainService.computeCountPerLine(tagBatch, preTagCountPerLine);
		for (int i = 0; i < tagCountPerLine - fieldsConfigCount; i++) {
			fieldsConfig.add(tagBatchConfigDomainService.defaultFieldConfig(tagBatch.getType(), fieldsConfig));
		}
		return fieldsConfig;
	}

}
